﻿namespace Knownet.BNF.Inline
{
  using System;
  using System.Text;
  using System.Collections;
  using System.Collections.Generic;
  using Knownet.AST;

  /// <summary>
  /// 关联指定匹配的语义动作。
  /// </summary>
  public delegate void SemanticAction(SyntaxNode currentSymbol);

  /// <summary>
  /// BNF子句。
  /// </summary>
  public class BnfClause : SyntaxNode
  {
    #region Consts
    /// <summary>
    /// Primitive连接符号，用于生成简单内联语法。
    /// </summary>
    public const string PrimitiveConcatSign = "*";
    #endregion
    #region Statics
    #region Shortcuts
    /// <summary>
    /// 生成缺省的子句实例。
    /// </summary>
    /// <returns></returns>
    public static new BnfClause CreateInstance()
    {
      return new BnfClause();
    }
    /// <summary>
    /// 生成由BnfPrimitive构成的子句。
    /// </summary>
    public static BnfClause succeeding(params BnfPrimitive[] items)
    {
      return new BnfClause(items);
    }
    #endregion
    #region Operators
    /// <summary>
    /// BnfClause转化到BnfDefinition的重载。
    /// </summary>
    public static implicit operator BnfDefinition(BnfClause clause)
    {
      return BnfDefinition.accordingTo(string.Empty, clause);
    }
    /// <summary>
    /// 子句选择的重载。
    /// </summary>
    public static BnfDefinition operator +(BnfClause firstClause, BnfClause secondClause)
    {
      return BnfDefinition.accordingTo(string.Empty, firstClause, secondClause);
    }
    /// <summary>
    /// 子句选择的重载。
    /// </summary>
    public static BnfDefinition operator +(BnfClause firstClause, BnfPrimitive primitive)
    {
      return BnfDefinition.accordingTo(string.Empty, firstClause, BnfClause.succeeding(primitive));
    }
    /// <summary>
    /// 关联语义动作。
    /// </summary>
    public static BnfClause operator /(BnfClause clause, SemanticAction actiontMethod)
    {
      if (clause != null)
      {
        clause.Action = actiontMethod;
      }
      return clause;
    }
    #endregion
    #endregion
    #region Fields
    /// <summary>
    /// 当前子句挂接的语义动作。
    /// </summary>
    protected SemanticAction action = null;
    #endregion
    #region Properties
    /// <summary>
    /// 获取或者设置当前子句挂接的语义动作。
    /// </summary>
    public virtual SemanticAction Action
    {
      get
      {
        return this.action;
      }
      set
      {
        this.action = value;
      }
    }
    /// <summary>
    /// 判别当前子句是否是终结符封装。
    /// </summary>
    /// <remarks>
    /// 所谓终结符封装，即子句中的
    /// 所有Primitive都是终结符。
    /// </remarks>
    public virtual bool IsTerminalWrapper
    {
      get
      {
        if (this.HasContainingNodes)
        {
          foreach (BnfPrimitive primitive in this.ContainingNodes)
          {
            if (!(primitive.IsLiteral))
            {
              return false;
            }
          }
        }
        return true;

      }
    }
    /// <summary>
    /// 判别当前子句是否是引用的封装。
    /// </summary>
    /// <remarks>
    /// 所谓引用封装，即子句中
    /// 的所有Primitive都是引用。
    /// </remarks>
    public virtual bool IsReferenceWrapper
    {
      get
      {
        if (this.HasContainingNodes)
        {
          foreach (BnfPrimitive primitive in this.ContainingNodes)
          {
            if (!(primitive.IsReference))
            {
              return false;
            }
          }
        }
        return true;

      }
    }
    /// <summary>
    /// 获取当前子句的Primitive列表。
    /// </summary>
    public virtual List<SyntaxNode> Primitives
    {
      get
      {
        return this.ContainingNodes;
      }
    }
    #endregion
    #region Constructors
    public BnfClause(params BnfPrimitive[] items)
    {
      this.Join(items);
    }
    #endregion
    #region Methods
    /// <summary>
    /// 将其他BnfPrimitive连接到当前子句，以构成子句定义。
    /// </summary>
    public virtual BnfClause Join(params BnfPrimitive[] items)
    {
      if (items != null)
      {
        foreach (BnfPrimitive item in items)
        {
          this.AddContainingNodes(item);
        }
      }
      return this;
    }
    /// <summary>
    /// 重载生成简化内联语法。
    /// </summary>
    public override string ToString()
    {
      StringBuilder builder = new StringBuilder();
      if (this.HasContainingNodes)
      {
        for (int i = 0; i < this.ContainingNodes.Count; i++)
        {
          builder.Append(this.ContainingNodes[i].ToString());
          if (i != this.ContainingNodes.Count - 1)
          {
            builder.AppendFormat(" {0} ", PrimitiveConcatSign);
          }
        }
      }
      return builder.ToString();
    }
    #endregion
  }
}
